local util = require "util"
local conf = require "conf"
local require = require
local setmetatable = setmetatable
local error = error
local table = table
local ngx = ngx
local os = os
local string = string
local tonumber = tonumber
local pairs = pairs
local message = require 'message'
package.cpath = "/usr/nginx/?.so;;"
local json = require 'cjson'
module(...)
_VERSION = '0.1'

function  create(user, args)
    local db = conf.get_mysql()
    local userModule = require 'user'
    local sql = "INSERT INTO `spoint` SET"
    local confirm_admin = conf.userDetail({["id"] = 118})

    if args.phone then
        sql = sql .. " phone = '" .. args.phone .. "',"
    else
        sql = sql .. " phone = '" .. user.phone .. "',"
    end

    if args.phone2 then
        sql = sql .. " phone2 = '" .. args.phone2 .. "',"
    else
        sql = sql .. " phone2 = '" .. confirm_admin.phone .."',"
    end

    if args.aid then
        sql = sql .. " aid = " .. args.aid .. ","
    else
        sql = sql .. " aid = " .. user.aid .. ","
    end
    if args.org_id then
        sql = sql .. " org_id = " .. args.org_id .. ","
    else
        sql = sql .. " org_id = " .. user.org_id .. ","
    end

    if args.uid then
        sql = sql .. " uid = " .. args.uid .. ","
    else
        sql = sql .. " uid = " .. user.id .. ","
    end

    if args.uid2 then
        sql = sql .. " uid2 = " .. args.uid2 .. ","
    else
        sql = sql .. " uid2 = " .. confirm_admin.id .. ","
    end

    if args.address then
        sql = sql .. " address = '" .. args.address .. "',"
    end
    if args.lng then
        sql = sql .. " lng = " .. args.lng .. ","
    end
    if args.lat then
        sql = sql .. " lat = " .. args.lat .. ","
    end
    if args.alt then
        sql = sql .. " alt = " .. args.alt .. ","
    end
    if args.name then
        sql = sql .. " name = '" .. args.name .. "',"
    end
    if args.contact_name2 then
        sql = sql .. " contact_name2 = '" .. args.contact_name2 .. "',"
    else
        sql = sql .. " contact_name2 = '" .. confirm_admin.name .. "',"
    end
    if args.contact_name then
        sql = sql .. " contact_name = '" .. args.contact_name .. "',"
    else
        sql = sql .. " contact_name = '" .. user.name .. "',"
    end

    sql = sql .. " update_time = " .. os.time() .. ","

    sql = sql .. " create_time = " .. os.time() .. ","
    ngx.log(ngx.ERR, sql)
    local res, err = db:query(sql:sub(1, -2))
    -- ngx.log(ngx.ERR, json.encode(err))
    return res
end

function createController(user, args)
    local db = conf.get_mysql()
    if args.name then
        local res = search(user, {["exactName"] = args.name})
        if res and #res > 0 then
            ngx.print(json.encode({
                err = 2,
                msg = '名称重复'
            }))
            ngx.exit(200)
        end
    end
    local res = create(user, args)
    if not res or res.affected_rows < 1 then
        ngx.print(json.encode({
            err = 1,
            msg = '创建失败'
        }))
        ngx.exit(200)
    else
        local insert_id = res.insert_id
        if insert_id < 1 then
            res = db:query("SELECT LAST_INSERT_ID() AS insert_id")
            if res and res[1] and res[1].insert_id then
                insert_id = res[1].insert_id
            end
        end
        local body = user.name .. "于" .. os.date("%H:%M", os.time()) .. "创建了" .. args.name .. "站点"
        message.create(user, {["to_uid"] = 0, ["type"] = "notice", ["header"] = "系统消息", ["body"] = body})
        ngx.print(json.encode({
            err = 0,
            id = insert_id,
            msg = '创建成功'
        }))
        ngx.exit(200)
    end 
end


function registerController(user, args)
    local db = conf.get_mysql()
    local red = conf.get_redis()
    local res = search(user, args)
    if res and res[1] then
        res = update(user, args)
    else
        res = create(user, args)
    end
    -- local res = create(user, args)
    if not res then
        ngx.print(json.encode({
            err = 1,
            msg = '注册失败'
        }))
        ngx.exit(200)
    else

        ngx.print(json.encode({
            err = 0,
            msg = '注册成功'
        }))
        ngx.exit(200)
    end 
end


-- function getInfo(page_no, page_size, id)
--     local conf = require "conf"
--     local json = require "cjson"
--     local db = conf.get_mysql()
--     local res = nil
--     local count = nil
--     local sql = "SELECT `spoint`.id, `spoint`.name,`spoint`.lat , `spoint`.lng, `spoint`.phone, `area`.name AS area, `area`.id AS aid FROM `spoint` left join `area` on `spoint`.aid = `area`.id WHERE disabled = 0"
--     if id then
--         sql = sql .. " AND `spoint`.id = " .. id
--     end
--     count = #db:query(sql)
--     sql = sql ..  " LIMIT " .. (page_no * page_size) .. "," .. page_size
--     res = db:query(sql)
--     if not res then
--         ngx.print(json.encode({
--             err = 0,
--             msg = {}
--         }))
--         ngx.exit(200)
--     else
--         ngx.print(json.encode({
--             err = 0,
--             count = count,
--             msg = res
--         }))
--         ngx.exit(200)
--     end
-- end

function update(user, args)
    local db = conf.get_mysql()
    local sql = "UPDATE `spoint` SET "

    if args.aid then
        sql = sql .. " aid = " .. args.aid .. ","
    end
    if args.org_id then
        sql = sql .. " aid = " .. args.org_id .. ","
    end
    if args.contact_name then
        sql = sql .. " contact_name = '" .. args.contact_name .. "',"
    else
        sql = sql .. " contact_name = '',"
    end
    if args.lng then
        sql = sql .. " lng = " .. args.lng .. ","
    end
    if args.lat then
        sql = sql .. " lat = " .. args.lat .. ","
    end
    if args.name then
        sql = sql .. " name = '" .. args.name .. "',"
    end
    if args.contact_name2 then
        sql = sql .. " contact_name2 = '" .. args.contact_name2 .. "',"
    else
        sql = sql .. " contact_name2 = '',"
    end
    if args.phone then
        sql = sql .. " phone = '" .. args.phone .. "',"
    else
        sql = sql .. " phone = '',"
    end
    if args.phone2 then
        sql = sql .. " phone2 = '" .. args.phone2 .. "',"
    else
        sql = sql .. " phone2 = '',"
    end
    if args.address then
        sql = sql .. " address = '" .. args.address .. "',"
    end
    if args.uid then
        sql = sql .. " uid = " .. args.uid .. ","
    else
        sql = sql .. " uid = 0,"
    end

    if args.uid2 then
        sql = sql .. " uid2 = " .. args.uid2 .. ","
    else
        sql = sql .. " uid2 = 0,"
    end
    if args.alt then
        sql = sql .. " alt = " .. args.alt .. ","
    end
    sql = sql .. " update_time = " .. os.time() .. ","
    ngx.log(ngx.ERR, sql)
    local res = db:query(sql:sub(1, -2) .. " WHERE id = " .. args.id )
    return res
end

function updateController(user, args)
    if not args.id then
        ngx.print(json.encode({
            err = 2,
            msg = '缺少id'
        }))
    end
    if args.name then
        local res = search(user, {["exactName"] = args.name})
        if res and #res > 0 and  res[1].id ~= args.id then
            ngx.print(json.encode({
                err = 2,
                msg = '名称重复'
            }))
            ngx.exit(200)
        end
    end

    local res = update(user, args)

    if not res then
        ngx.print(json.encode({
            err = 1,
            msg = '更新失败'
        }))
        ngx.exit(200)
    else 
        ngx.print(json.encode({
            err = 0,
            msg = res
        }))
        ngx.exit(200)
    end
end

function delete(user, args)
    local id = args.id
    local db = conf.get_mysql()
    local res = db:query("UPDATE `spoint` SET disabled = 1 WHERE id = " .. id )
    return res
end

function deleteController(user, args)
    if not args.id then
        ngx.print(json.encode({
            err = 2,
            msg = '缺少id'
        }))
    end
    local res = delete(user, args)
    if not res or res.affected_rows < 1 then
        ngx.print(json.encode({
            err = 1,
            msg = '更新失败'
        }))
        ngx.exit(200)
    else 
        ngx.print(json.encode({
            err = 0,
            msg = res
        }))
        ngx.exit(200)
    end
end

function search(user, args)
    local page_no, page_size, id, name, aid, contact_name, pid = tonumber(args.page_no), tonumber(args.page_size), args.id, args.name, args.aid, args.contact_name, args.pid
    local db = conf.get_mysql()
    local schedule = require "schedule"
    local plane = require "plane"
    local now  = os.time()
    local arrive = " (SELECT count(`order`.id) from `order` left JOIN `route` on `order`.route = `route`.id WHERE `order`.fid in (SELECT `plane`.id FROM `plane` where `plane`.model != 'sim') AND (`order`.t4 BETWEEN " .. now - 3600 .. " AND " .. now .." OR `order`.t5 BETWEEN " .. now - 3600 .. " AND " .. now ..") AND `route`.eid = `spoint`.id) AS arrive,"
    local takeoff = " (SELECT count(`order`.id) from `order` left JOIN `route` on `order`.route = `route`.id WHERE `order`.fid in (SELECT `plane`.id FROM `plane` where `plane`.model != 'sim') AND `order`.t2 BETWEEN " .. now - 3600 .. " AND " .. now .." AND `route`.sid = `spoint`.id) AS takeoff,"
    local day_arrive =  " (SELECT count(`order`.id) from `order` left JOIN `route` on `order`.route = `route`.id WHERE `order`.fid in (SELECT `plane`.id FROM `plane` where `plane`.model != 'sim') AND (`order`.t4 BETWEEN " .. util.zero_clock_of_day(now) .. " AND " .. now .." OR `order`.t5 BETWEEN " .. util.zero_clock_of_day(now) .. " AND " .. now ..") AND `route`.eid = `spoint`.id) AS daily_arrive,"
    local day_takeoff =  " (SELECT count(`order`.id) from `order` left JOIN `route` on `order`.route = `route`.id WHERE `order`.fid in (SELECT `plane`.id FROM `plane` where `plane`.model != 'sim') AND `order`.t2 BETWEEN " .. util.zero_clock_of_day(now) .. " AND " .. now .." AND `route`.sid = `spoint`.id) AS daily_takeoff,"
    local month_arrive =  " (SELECT count(`order`.id) from `order` left JOIN `route` on `order`.route = `route`.id WHERE `order`.fid in (SELECT `plane`.id FROM `plane` where `plane`.model != 'sim') AND (`order`.t4 BETWEEN " .. util.zero_clock_of_month(now) .. " AND " .. now .." OR `order`.t5 BETWEEN " .. util.zero_clock_of_month(now) .. " AND " .. now ..") AND `route`.eid = `spoint`.id) AS monthly_takeoff,"
    local month_takeoff =  " (SELECT count(`order`.id) from `order` left JOIN `route` on `order`.route = `route`.id WHERE `order`.fid in (SELECT `plane`.id FROM `plane` where `plane`.model != 'sim') AND `order`.t2 BETWEEN " .. util.zero_clock_of_month(now) .. " AND " .. now .." AND `route`.sid = `spoint`.id) AS monthly_arrive,"
    -- local all = arrive .. takeoff .. day_arrive .. day_takeoff .. month_arrive .. month_takeoff
    local all = "'-' as arrive, '-' as takeoff, 0 as day_arrive, 0 as day_takeoff, 0 as month_arrive, 0 as month_takeoff,"
    local sql = "SELECT `spoint`.contact_name,`spoint`.contact_name2, `spoint`.pid, `spoint`.id, `spoint`.name, `spoint`.update_time, (SELECT COUNT(id) FROM `plane` WHERE `plane`.`spoint_id`= `spoint`.id AND `plane`.model != 'sim' AND status = 0) AS status_0," .. all .. " `spoint`.address, `spoint`.lat , `spoint`.lng, `spoint`.alt, `spoint`.org_id, `spoint`.phone, `spoint`.phone2, `spoint`.uid, `spoint`.uid2,`area`.name AS area, `area`.id AS aid,`area`.weather, `area`.wind  FROM `spoint` left join `area` on `spoint`.aid = `area`.id WHERE `spoint`.disabled = 0";
    if name then
        sql = sql .. " AND `spoint`.name like '%" .. name .. "%'"
    end
    if args.exactName then
        sql = sql .. " AND `spoint`.name = '" .. args.exactName .. "'"
    end
    if contact_name then
        sql = sql .. " AND `spoint`.contact_name like '%" .. contact_name .. "%'"
    end
    if aid then
        local ids = conf.get_aids(tonumber(aid))
        sql = sql .. " AND `spoint`.aid in (" ..  table.concat(ids, ",") .. ")"
    end

    if args.org_id then
        local ids = conf.get_orgIds(tonumber(args.org_id))
        sql = sql .. " AND `spoint`.org_id in (" ..  table.concat(ids, ",") .. ")"
    end

    if id then
        sql = sql .. " AND `spoint`.id = " .. id
    end
    
    if args.uid then
        sql = sql .. " AND (`spoint`.uid = " .. args.uid .. "OR `spoint`.uid2 = " .. args.uid .. ")" 
    end

    sql = sql .. " AND `spoint`.aid in (" ..  table.concat(user.aids, ",") .. ")"

    sql = sql .. " AND `spoint`.org_id in (" ..  table.concat(user.orgIds, ",") .. ")"

    sql = sql .. " ORDER BY `spoint`.update_time DESC"

    ngx.log(ngx.ERR, sql)
    local count = #(db:query(sql) or {})

    if page_no and page_size then
        sql = sql ..  " LIMIT " .. (page_no * page_size) .. "," .. page_size
    end
    local res = db:query(sql)
    if res then
        local scheduleSpoints = schedule.getActiveSpoints(user, {})
        -- ngx.log(ngx.ERR, json.encode(scheduleSpoints))
        local planesBySpoints = plane.getPlanesBySpoint()

        for k,v in pairs(res) do
            -- ngx.log(ngx.ERR, json.encode(v))
            local sp = scheduleSpoints[v.id .. ""] or {}
            v.planArrive = sp.planArrive or 0
            v.planTakeoff = sp.planTakeoff or 0
            v.planes = planesBySpoints[v.id .. ""] or {}
         end
    else
        return nil, 0
    end
    ngx.log(ngx.ERR, json.encode(res))
    return res,count
end

function searchController(user, args)
    local res, count = search(user, args)
    if not res then
        ngx.print(json.encode({
            err = 1,
            msg = '未找到相应的站点'
        }))
        ngx.exit(200)
    else
        ngx.print(json.encode({
            err = 0,
            msg = res,
            count = count
        }))
        ngx.exit(200)
    end

end

function getHeightDiffBySpointIds(sid, eid)
    local sql = "SELECT id, alt FROM `spoint` WHERE id = "
    local db = conf.get_mysql()
    local sp1 = db:query(sql .. sid)
    local sp2 = db:query(sql .. eid)
    if sp1 and sp1[1] and sp2 and sp2[1] then
        return tonumber(sp2[1].alt) - tonumber(sp1[1].alt)
    end
    return 0
end

function list(user, args)
    ngx.log(ngx.ERR, json.encode(user))
    local page_no, page_size, aid = tonumber(args.page_no), tonumber(args.page_size), args.aid
    local db = conf.get_mysql()
    local sql = "SELECT id, name, lng, lat, alt FROM `spoint`WHERE disabled = 0";

    sql = sql .. " AND aid in (" ..  table.concat(user.aids, ",") .. ")"

    sql = sql .. " AND org_id in (" ..  table.concat(user.orgIds, ",") .. ")"

    local count = #(db:query(sql) or {})

    if page_no and page_size then
        sql = sql ..  " LIMIT " .. (page_no * page_size) .. "," .. page_size
    end
    ngx.log(ngx.ERR, sql)
    local res = db:query(sql)
    return res, count
end

function listController(user, args)
    local res, count = list(user, args)
    if not res then
        ngx.print(json.encode({
            err = 1,
            msg = '未找到相应的站点'
        }))
        ngx.exit(200)
    else
        ngx.print(json.encode({
            err = 0,
            msg = res,
            count = count
        }))
        ngx.exit(200)
    end
end

function listCoordinates(user, args)
    local db = conf.get_mysql()
    local sql = "SELECT `spoint`.id, `spoint`.aid, `area`.name as areaName, `spoint`.lng, `spoint`.lat, `spoint`.alt FROM `spoint` left join `area` on `spoint`.aid = `area`.id WHERE `spoint`.disabled = 0 AND aid in (" ..  table.concat(user.aids, ",") .. ")";
    local res = db:query(sql)
    return res
end

function listCoordinatesController(user, args)
    local res = listCoordinates(user, args)
    if not res then
        ngx.print(json.encode({
            err = 1,
            msg = '未找到相应的站点'
        }))
        ngx.exit(200)
    else
        ngx.print(json.encode({
            err = 0,
            msg = res,
            count = count
        }))
        ngx.exit(200)
    end
end

function getMapReqPoints(user, args)
    local w = 0.12
    local sp = search(user, args)
    if sp and sp[1] then
        local lat, lng = sp[1].lat, sp[1].lng
        return {{lat - w, lng + w}, {lat + w, lng - w}}
    end
    return {{0,0},{0,0}}
end

function getMapReqPointsController(user, args)
    if not args.id then
        ngx.print(json.encode({
            err = 2,
            msg = '缺少id'
        }))
        ngx.exit(200)
    end

    local res = getMapReqPoints(user, args)

    ngx.print(json.encode({
        err = 0,
        msg = res
    }))
    ngx.exit(200)
end

function default(args)
    local user = conf.parse_token(args, "spoint")
    if args.action == 'create' then
        createController(user, args)
    elseif args.action == 'update' then
        updateController(user, args)
    elseif args.action == 'search' then
        searchController(user, args)
    elseif args.action == 'delete' then
        deleteController(user, args)
    elseif args.action == 'list' then
        listController(user, args)
    elseif args.action == 'listCoordinates' then
        listCoordinatesController(user, args)
    elseif args.action == 'getMapReqPoints' then
        getMapReqPointsController(user, args)
    end
end

local class_mt = {
    __newindex = function (table, key, val)
        error('attempt to write to undeclared variable "' .. key .. '"')
    end
}
setmetatable(_M, class_mt)
